<template>
  <div class="code-editor-container">
    <div class="editor-section">
      <div class="toolbar">
        <label class="auto-run-label">
          <input type="checkbox" v-model="autoRun" />
          自动运行
        </label>
        <button class="run-btn" @click="runCode" :disabled="autoRun">运行</button>
      </div>
      <Codemirror
        v-model="vueCode"
        placeholder="代码..."
        :style="{ height: '100vh', width: '50vw' }"
        :autofocus="true"
        :indent-with-tab="true"
        :tab-size="2"
        :extensions="vueExtensions"
      />
    </div>
    <div class="preview-section">
      <iframe :srcdoc="displayedCode" class="preview-iframe"></iframe>
    </div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { html } from '@codemirror/lang-html';
import { javascript } from '@codemirror/lang-javascript';
import { css } from '@codemirror/lang-css';
import { oneDark } from '@codemirror/theme-one-dark';
// .vue 文件初始内容
const vueCode = ref(
  `<template>\n  <div id=\"app\">\n    <h1>Hello, Vue 3!</h1>\n    <p>{{ msg }}</p>\n  </div>\n</template>\n\n<script setup>\nconst msg = '这是 .vue 文件内容编辑示例'\n<\/script>\n\n<style scoped>\nh1 { color: #42b983; }\n<\/style>`
);

// 组合高亮 .vue 文件的扩展
// const vueExtensions = [html(), javascript(), css()]
const vueExtensions = [javascript(), html(), javascript(), css(), oneDark];
const autoRun = ref(true);
const displayedCode = ref('');

// 解析 .vue 文件，拼接为可预览的 HTML
function parseVueToHtml(vueSrc) {
  const templateMatch = vueSrc.match(/<template>([\s\S]*?)<\/template>/);
  const scriptMatch = vueSrc.match(/<script.*?>([\s\S]*?)<\/script>/);
  const styleMatch = vueSrc.match(/<style.*?>([\s\S]*?)<\/style>/);
  const template = templateMatch ? templateMatch[1] : '';
  const script = scriptMatch ? scriptMatch[1] : '';
  const style = styleMatch ? styleMatch[1] : '';
  // 仅支持 <script setup> 的简单变量渲染
  let renderedTemplate = template;
  if (script.includes('const msg')) {
    const msgValue = script.match(/const msg\s*=\s*['\"]([\s\S]*?)['\"]/);
    if (msgValue) {
      renderedTemplate = renderedTemplate.replace(/{{\s*msg\s*}}/g, msgValue[1]);
    }
  }
  return `<!DOCTYPE html>\n<html>\n<head>\n<style>${style}</style>\n</head>\n<body>\n${renderedTemplate}\n<script>${script}<\/script>\n</body>\n</html>`;
}

function runCode() {
  displayedCode.value = parseVueToHtml(vueCode.value);
}

watch(
  [vueCode, autoRun],
  ([code, auto]) => {
    if (auto) {
      displayedCode.value = parseVueToHtml(code);
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.code-editor-container {
  display: flex;
  flex-direction: row;
  height: 100vh;
}
.toolbar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 12px 24px;
  position: sticky;
  top: 0;
  z-index: 10;
  box-shadow: 0 2px 8px 0 rgba(60, 60, 60, 0.03);
  position: absolute;
  color: #fff;
  right:0;
}
.auto-run-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  user-select: none;
}
.run-btn {
  padding: 6px 18px;
  background: #42b983;
  color: #fff;
  border: none;
  border-radius: 4px;
  font-size: 15px;
  cursor: pointer;
  transition: background 0.2s;
}
.run-btn:disabled {
  background: #b2dfc7;
  cursor: not-allowed;
}
.editor-section {
  flex: 1.1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  position: relative;
}

.preview-section {
  flex: 1;
  padding: 16px 24px 16px 12px;
  background: #fff;
  border-left: 1px solid #e5e7eb;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.preview-iframe {
  flex: 1;
  width: 100%;
  border: none;
  background: #fff;
  border-radius: 6px;
  box-shadow: 0 2px 8px 0 rgba(60, 60, 60, 0.03);
}
</style>
